package com.yeskery.nut.extend.datasource.hikaricp;

import com.yeskery.nut.application.ServerEventContext;
import com.yeskery.nut.extend.datasource.DataSourcePlugin;
import com.yeskery.nut.plugin.ApplicationContextSupportBasePlugin;
import com.yeskery.nut.plugin.PluginBeanMetadata;
import com.yeskery.nut.util.StringUtils;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import javax.sql.DataSource;
import java.util.Collection;
import java.util.Collections;
import java.util.function.Consumer;

/**
 * HikariCP连接池插件
 * @author sprout
 * @version 1.0
 * 2022-07-10 18:55
 */
public class HikaricpPlugin extends ApplicationContextSupportBasePlugin implements DataSourcePlugin {

    /** JDBC驱动类名称 */
    private final String driverClassName;

    /** JDBC URL */
    private final String url;

    /** JDBC 用户名 */
    private final String username;

    /** JDBC 密码 */
    private final String password;

    /** 数据源配置消费者 */
    private final Consumer<HikariConfig> dataSourceConfigConsumer;

    /** 连接池对象 */
    private HikariDataSource dataSource;

    /**
     * 构建Druid连接池插件
     * @param driverClassName JDBC驱动类名称
     * @param url JDBC URL
     * @param username JDBC 用户名
     * @param password JDBC 密码
     */
    public HikaricpPlugin(String driverClassName, String url, String username, String password) {
        this(driverClassName, url, username, password, null);
    }

    /**
     * 构建Druid连接池插件
     * @param driverClassName JDBC驱动类名称
     * @param url JDBC URL
     * @param username JDBC 用户名
     * @param password JDBC 密码
     * @param consumer 数据源配置消费者
     */
    public HikaricpPlugin(String driverClassName, String url, String username, String password, Consumer<HikariConfig> consumer) {
        this.driverClassName = driverClassName;
        this.url = url;
        this.username = username;
        this.password = password;
        this.dataSourceConfigConsumer = consumer;
    }

    @Override
    protected Collection<PluginBeanMetadata> getRegisterPluginBeanMetadata() {
        HikariConfig hikariConfig = new HikariConfig();
        if (!StringUtils.isEmpty(driverClassName)) {
            hikariConfig.setDriverClassName(driverClassName);
        }
        if (!StringUtils.isEmpty(url)) {
            hikariConfig.setJdbcUrl(url);
        }
        if (!StringUtils.isEmpty(username)) {
            hikariConfig.setUsername(username);
        }
        if (!StringUtils.isEmpty(password)) {
            hikariConfig.setPassword(password);
        }
        initialized(hikariConfig);
        if (dataSourceConfigConsumer != null) {
            dataSourceConfigConsumer.accept(hikariConfig);
        }
        dataSource = new HikariDataSource(hikariConfig);
        return Collections.singletonList(new PluginBeanMetadata("dataSource", dataSource,
                DataSource.class, HikariDataSource.class));
    }

    @Override
    public DataSource getDataSource() {
        return dataSource;
    }

    @Override
    public void beforeClose(ServerEventContext serverEventContext) {
        if (dataSource != null) {
            dataSource.close();
        }
    }

    /**
     * 初始化HikariCP数据源
     * @param hikariConfig HikariCP配置对象
     */
    private void initialized(HikariConfig hikariConfig) {
        hikariConfig.setMaximumPoolSize(20);
        hikariConfig.setMinimumIdle(5);
    }
}
